package myJs.cps.project

import myJs.api.Api
import myJs.cps.BootstrapTableCp.Column
import myJs.cps.{BootstrapTableCp, Style}
import myJs.myPkg.layer
import myJs.myPkg.reactBootstrap.{OverlayTrigger, Popover}
import myJs.tool.Pojo._
import myJs.tool.Tool
import slinky.core.FunctionalComponent
import slinky.core.annotations.react
import slinky.core.facade.Hooks.{useEffect, useState}
import slinky.core.facade.ReactElement
import slinky.web.html._
import upickle.default.write

import scala.collection.immutable.SeqMap
import scala.scalajs.js
import myJs.Implicits._
import org.scalajs.macrotaskexecutor.MacrotaskExecutor.Implicits._

/**
 * Created by yz on 21/1/2022
 */
@react object MarkerCp {

  case class Props(showLoading: Boolean = true)

  val component = FunctionalComponent[Props] { props =>

    val (datas, setDatas) = useState(List.empty[ujson.Obj])
    val (columns, setColumns) = useState(List.empty[Column])

    object FTool {

      def refreshColumns = () => {
        val map = SeqMap(
          "cellType" -> "Cell_Type",
          "lineage" -> "Lineage",
          "clusterResolution" -> "Cluster_Resolution",
          "avgLog2fc" -> "Avg_log2FC",
          "pct1" -> "Pct.1",
          "pct2" -> "Pct.2",
          "marker" -> "Marker",
          "pval" -> "Pval",
          "pvalAdj" -> "Pval_adj",
          "suggestedLabels" -> "Suggested_Labels",
        )
        val basicColumns = map.map { case (k, v) =>
          val searchKind = k match {
            case "avgLog2fc" | "pct1" | "pct2" | "pval" | "pvalAdj" => DoubleSearch
            case _ => TextSearch
          }
          val title = v match {
            case _ => v
          }
          val operable = k match {
            case "species" => false
            case _ => true
          }
          val fmt = FTool.tbFmt(k)
          val comVF = FTool.comVFmt(v)
          val defaultValue = v match {
            case _ => ""
          }
          Column(field = k, title = title, operable = operable, searchKind = searchKind, formatter = fmt,
            comVF = comVF)
        }.toList
        setColumns(basicColumns)
      }

      def tbFmt(fileTitle: String) = (v: ujson.Value, row: ujson.Obj) => {
        fileTitle match {
          case "Avg_log2FC" | "P_val" =>
            span(v.str.toDouble.toFixed(3))()
          case _ => span(v.myStr)()
        }
      }

      def comVFmt(fileTitle: String) = (v: ujson.Value, row: ujson.Obj) => {
        fileTitle match {
          case _ => v.myStr
        }
      }

      def ajaxRequest = (limit: Int, offset: Int,
                         searchMap: SeqMap[String, SearchData], sortDataOp: Option[SortData], allSearch: String) => {
        val index = if (props.showLoading) {
          val options = Tool.layerOptions.copy(shade = List("0.1", "#fff"))
          layer.load(0, options)
        } else 0
        val trueSortObj = if (sortDataOp.isEmpty) {
          ujson.Obj()
        } else {
          val sortData = sortDataOp.get
          ujson.Obj("sort" -> ujson.Obj(
            "field" -> sortData.field,
            "kind" -> sortData.kind,
            "order" -> sortData.order,
          ))
        }
        val searchs = searchMap.map { case (k, searchData) =>
          searchData match {
            case TextSearchData(searchType, text) =>
              ujson.Obj(
                "name" -> k,
                "kind" -> "text",
                "searchType" -> searchType,
                "value" -> text,
              )
            case NumericSearchData(min, max, kind) =>
              ujson.Obj(
                "name" -> k,
                "kind" -> kind,
                "min" -> Tool.dbFmt(min),
                "max" -> Tool.dbFmt(max),
              )
            case CheckboxSearchData(values) =>
              ujson.Obj(
                "name" -> k,
                "kind" -> "checkbox",
                "value" -> values,
              )
          }
        }.toList
        val trueSearchObj = ujson.Obj("search" -> searchs)
        val obj = ujson.Obj(
          "limit" -> limit,
          "offset" -> offset,
          "allSearch" -> allSearch
        ) ++ trueSortObj ++ trueSearchObj
        val dataStr = write(obj)
        Api.marker.allByServer(dataStr).map { obj =>
          layer.close(index)
          obj
        }

      }

    }

    useEffect(() => {
      FTool.refreshColumns()
    }, List()
    )

    val exportDatas = List(
      ExportData("XLSX", href = s"${Api.apiUrl}/gepLiver/tool/downloadFile?fileName=marker.xlsx")
    )

    div(
      h5(style := Style(marginBottom = 15, fontSize = 16, marginTop = 15), id := "sMarker",
        "Marker List ",
        {
          val popover: ReactElement = Popover(id = "popover-basic")(
            Popover.Title("Note"),
            Popover.Content(
              "Differentially expressed genes for all clusters"
            )
          )
          OverlayTrigger(
            placement = "right",
            trigger = js.Array("focus", "hover"),
            overlay = popover
          )(
            span(
              a(`type` := "button",
                i(className := "fas fa-info-circle")
              )
            )
          )
        }
      ),
      BootstrapTableCp(columns = columns, datas = datas, pageList = List(10, 25, 50), pageSize = 10,
        selectColumnEnabled = true, showColumnNum = 6, sidePagination = "server", ajax = FTool.ajaxRequest,
        exportData = exportDatas, showExport = true)
    )


  }

  object STool {


  }

}
